<template>
  <n-modal max-w-800 v-model:show="showModel" preset="card" :title="title">
    <n-grid cols="3 650:7" y-gap="20">
      <n-gi span="4">
        <cropper-image
          :src="src"
          class="h-300! w-full!"
          :circled="circled"
          @cropend="handleCropend"
          @ready="handleReady"
        />
        <n-space justify="space-between" mt-10>
          <n-upload accept="image/*" :on-before-upload="handleBeforeUpload">
            <tooltip label="选择图片">
              <n-button size="small" type="primary">
                <icon-ant-design-upload-outlined />
              </n-button>
            </tooltip>
          </n-upload>
          <n-space>
            <tooltip label="重置">
              <n-button
                size="small"
                type="primary"
                :disabled="!src"
                @click="cropper?.reset()"
              >
                <icon-ant-design-reload-outlined />
              </n-button>
            </tooltip>
            <tooltip label="逆时针旋转">
              <n-button
                size="small"
                type="primary"
                :disabled="!src"
                @click="cropper?.rotate(-45)"
              >
                <icon-ant-design-rotate-left-outlined />
              </n-button>
            </tooltip>
            <tooltip label="顺时针旋转">
              <n-button
                size="small"
                type="primary"
                :disabled="!src"
                @click="cropper?.rotate(45)"
              >
                <icon-ant-design-rotate-right-outlined />
              </n-button>
            </tooltip>
            <tooltip label="水平翻转">
              <n-button
                size="small"
                type="primary"
                :disabled="!src"
                @click="
                  () => {
                    scaleX = 0 - scaleX;
                    cropper?.scaleX(scaleX);
                  }
                "
              >
                <icon-vaadin-arrows-long-h />
              </n-button>
            </tooltip>
            <tooltip label="垂直翻转">
              <n-button
                size="small"
                type="primary"
                :disabled="!src"
                @click="
                  () => {
                    scaleY = 0 - scaleY;
                    cropper?.scaleY(scaleY);
                  }
                "
              >
                <icon-vaadin-arrows-long-v />
              </n-button>
            </tooltip>
            <tooltip label="放大">
              <n-button
                size="small"
                type="primary"
                :disabled="!src"
                @click="cropper?.zoom(0.1)"
              >
                <icon-ant-design-zoom-in-outlined />
              </n-button>
            </tooltip>
            <tooltip label="缩小">
              <n-button
                size="small"
                type="primary"
                :disabled="!src"
                @click="cropper?.zoom(-0.1)"
              >
                <icon-ant-design-zoom-out-outlined />
              </n-button>
            </tooltip>
          </n-space>
        </n-space>
      </n-gi>
      <n-gi span="3">
        <div f-c-c f-col w-full>
          <n-avatar :round="circled" :src="previewSource" :size="200" />
          <n-divider class="w-290 my-10!" />
          <n-space align="center" item-style="margin-left: 10px">
            <n-avatar :round="circled" :src="previewSource" :size="40" />
            <n-avatar :round="circled" :src="previewSource" :size="50" />
            <n-avatar :round="circled" :src="previewSource" :size="60" />
            <n-avatar :round="circled" :src="previewSource" :size="70" />
          </n-space>
        </div>
      </n-gi>
    </n-grid>
    <n-space justify="end">
      <n-space>
        <n-button @click="handleCancel">{{ negativeText }}</n-button>
        <n-button
          type="info"
          :loading="loading"
          :disabled="!src"
          @click="handleOk"
        >
          {{ positiveText }}
        </n-button>
      </n-space>
    </n-space>
  </n-modal>
</template>

<script lang="tsx" setup>
import CropperImage from "../cropper/index.vue";
import { CropendResult } from "../cropper/types";
import { useVModel } from "@vueuse/core";
import { base64ToBlob } from "@/utils";
import { UploadFileInfo } from "naive-ui";

interface Props {
  show: boolean;
  loading?: boolean;
  title?: string;
  negativeText?: string;
  positiveText?: string;
  circled?: boolean;
  src?: string;
  /** 上传文件最大大小（mb） */
  size?: number;
}
interface Emits {
  (e: "update:show", p: boolean): void;
  (e: "negativeClick"): void;
  (e: "positiveClick", p: { file: Blob; filename: string }): void;
  (e: "uploadError", p: string): void;
}
const props = withDefaults(defineProps<Props>(), {
  negativeText: "取消",
  positiveText: "确认上传",
});
const emits = defineEmits<Emits>();
const showModel = useVModel(props, "show", emits);

let filename = "";
const src = ref(props.src || "");
const previewSource = ref("");
const cropper = ref<Cropper>();
let scaleX = 1;
let scaleY = 1;

// Block upload
const handleBeforeUpload = ({
  file: uploadFile,
}: {
  file: UploadFileInfo;
  fileList: UploadFileInfo[];
}) => {
  const file = uploadFile.file;
  if (!file) return;
  if (props.size && file.size > 1024 * 1024 * props.size) {
    emits("uploadError", "image too big");
    return;
  }
  const reader = new FileReader();
  reader.readAsDataURL(file);
  src.value = "";
  previewSource.value = "";
  reader.onload = function (e) {
    src.value = (e.target?.result as string) ?? "";
    filename = file.name;
  };
  return false;
};

const handleCropend = ({ imgBase64 }: CropendResult) => {
  previewSource.value = imgBase64 as string;
};

const handleReady = (cropperInstance: Cropper) => {
  cropper.value = cropperInstance;
};

const handleOk = async () => {
  const file = base64ToBlob(previewSource.value);
  console.log(file);

  emits("positiveClick", { file, filename });
};
const handleCancel = () => {
  emits("negativeClick");
  showModel.value = false;
};
</script>

<style scoped></style>
